<?php

namespace app\admin\controller;

use addons\epay\library\Service;
use app\admin\model\IdentityInfo;
use app\common\controller\Backend;
use app\common\model\Test;
use think\Db;
use think\exception\DbException;
use think\exception\PDOException;
use think\exception\ValidateException;
use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;

/**
 * 订单管理
 *
 * @icon fa fa-circle-o
 */
class Order extends Backend
{

    /**
     * Order模型对象
     * @var \app\admin\model\Order
     */
    protected $model = null;
    
    protected $selectpageFields = 'id,order_no';

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\Order;

        $this->assign('getPayStatus', $this->model->getPayStatus());
        $this->assignconfig("getPayStatus", $this->model->getPayStatus());
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if (false === $this->request->isAjax()) {
            return $this->view->fetch();
        }
        //如果发送的来源是 Selectpage，则转发到 Selectpage
        if ($this->request->request('keyField')) {
            return $this->selectpage();
        }
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $and_where = ['pay_status'=>['<>','1']];
        $semester_arr = [
            1=>'一学期',
            2=>'两学期',
            3=>'三学期',
            4=>'四学期',
            5=>'五学期',
            6=>'六学期',
        ];
        $list = $this->model->with(['user','teacher','address','dtl'])
            ->where($where)
            ->where($and_where)
            ->order($sort, $order)
            ->paginate($limit)->each(function ($row) use($semester_arr) {
                $info = json_decode($row['info'],true);
                $row['club_name'] = isset($info['club_two']) ? $info['club_two'] : '';
                $row['dtl_info'] = '';
                foreach ($row['dtl'] as $k=>$v){
                    if($row['sign_type'] == '长期'){
                        $semester = isset($semester_arr[$v['semester']]) ? $semester_arr[$v['semester']] : '';
                        $info = $semester.'-'.$v['semester_hours'].'课时.';
                        $row['dtl_info'] .= $info;
                    }else{
                        $info = '上课时间:'.$v['class_date'].'-开始时间:'.$v['class_start_time'].'- '.$v['class_num'].'课时.  ';
                        $row['dtl_info'] .= $info;
                    }
                }
            });

        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }



    public function tuikuan($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            if (!in_array($row[$this->dataLimitField], $adminIds)) {
                $this->error(__('You have no permission'));
            }
        }
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                $params = $this->preExcludeFields($params);

                if (!$row['order_no']) {
                    $this->error('订单号不存在');
                }
                if($row['money']<=0){
                    $this->error('金额不可小于等于0');
                }
                switch ($row['type']){
                    case '支付宝':
                        $order = [
                            'out_trade_no' => $row['order_no'],
                            'refund_amount' => $row['money'],
                        ];
                        $refund = Service::refunds($order,'alipay');
                        if(!isset($refund['code'])){
                            $this->error($refund);
                        }
                        if($refund['code']=='10000'&&$refund['msg']=='Success'){
                            $out_refund_no = \app\admin\model\OrderRefunds::getOrderNo();
                            \app\admin\model\OrderRefunds::create(['title'=>'支付宝退款','out_order_id'=>$out_refund_no,'order_id'=>$row['order_no'],'money'=>$order['refund_amount'],'status'=>'SUCCESS','addtime'=>date('Y-m-d H:i:s'),'msg'=>'']);
                            $row->save(['pay_status'=>3]);
                            $res = \app\admin\model\Order::refund_success($row['order_no']);
                            if($res['code'] == 0){
                                $this->error($res['msg']);
                            }
                            $this->success();
                        }else{
                            $this->error(__('退款失败'));
                        }
                        break;
                    case '微信':
                        $order_no = $row['order_no'];
                        $order = \app\admin\model\Order::where(['order_no'=>$order_no])->find();

                        $merchantId = '1710092419';
                        // 从本地文件中加载「商户API私钥」，「商户API私钥」会用来生成请求的签名
                        $merchantPrivateKeyFilePath = 'file:///www/wwwroot/hainan.megmt.com/public/apiclient_key.pem';
                        $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
                        // 「商户API证书」的「证书序列号」
                        $merchantCertificateSerial = '1F49455BB07F3F1818168E1E21389FA89554968F';
                        // 从本地文件中加载「微信支付平台证书」(可使用证书下载工具得到），用来验证微信支付应答的签名
                        $platformCertificateFilePath = 'file:///www/wwwroot/hainan.megmt.com/public/wechatpay_77A215B745C4B7817B7DC820BD8AFC579779FB5C.pem';
                        $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
                        // 从「微信支付平台证书」中获取「证书序列号」
                        $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
                        // 构造一个 APIv3 客户端实例
                        $instance = Builder::factory([
                            'mchid'      => $merchantId,
                            'serial'     => $merchantCertificateSerial,
                            'privateKey' => $merchantPrivateKeyInstance,
                            'certs'      => [
                                $platformCertificateSerial => $platformPublicKeyInstance,
                            ],
                        ]);
                        $out_refund_no = \app\admin\model\OrderRefunds::getOrderNo();
                        $promise = $instance
                            ->chain('v3/refund/domestic/refunds')
                            ->postAsync([
                                'json' => [
                                    'out_trade_no' => $order_no,
                                    'out_refund_no'  => $out_refund_no,
                                    'notify_url'=>'http://school.xukebao.cn/index.php/api/demo/wxrefundcallback',
                                    'amount'         => [
                                        'refund'   => $order['money']*100,
                                        'total'    => $order['money']*100,
                                        'currency' => 'CNY',
                                    ],
                                ],
                            ])
                            ->then(static function($response) use($out_refund_no,$order_no,$order){
                                // 正常逻辑回调处理
                                $res = $response->getBody()->getContents();
                                $res_data = json_decode($res,true);
                                \app\admin\model\OrderRefunds::create(['title'=>'微信退款','out_order_id'=>$out_refund_no,'order_id'=>$order_no,'money'=>$order['money'],'status'=>$res_data['status'],'addtime'=>date('Y-m-d H:i:s'),'msg'=>'']);
                                return $response;
                            })
                            ->otherwise(static function($e) {
                                // 异常错误处理
                                echo $e->getMessage(), PHP_EOL;
                                if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
                                    $r = $e->getResponse();
                                    echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
                                    echo (string) $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
                                }
                                echo $e->getTraceAsString(), PHP_EOL;
                            });
                        // 同步等待
                        $promise->wait();

                        $row->save(['pay_status'=>3]);
                        $res = \app\admin\model\Order::refund_success($order_no);
                        if($res['code'] == 0){
                            $this->error($res['msg']);
                        }
                        $this->success();
                        break;
                    case '线下支付':
                        //线下支付退款
                        $order_no = $row['order_no'];
                        $order = \app\admin\model\Order::where(['order_no'=>$order_no])->find();
                        $out_refund_no = \app\admin\model\OrderRefunds::getOrderNo();
                        \app\admin\model\OrderRefunds::create(['title'=>'线下支付退款','out_order_id'=>$out_refund_no,'order_id'=>$order_no,'money'=>$order['money'],'status'=>'SUCCESS','addtime'=>date('Y-m-d H:i:s'),'msg'=>'']);
                        $res = \app\admin\model\Order::refund_success($order_no);
                        if($res['code'] == 0){
                            $this->error($res['msg']);
                        }
                        $row->save(['pay_status'=>3]);
                        $this->success();
                        break;
                    default:
                        $this->error('不支持退款的付款方式');
                        break;
                }

            }
        }

        $this->view->assign("row", $row);
        $this->view->assign("ids", $ids);
        return $this->view->fetch();
    }


    /**
     * 添加
     *
     * @return string
     * @throws \think\Exception
     */
    public function add()
    {
        if (false === $this->request->isPost()) {
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);

        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
            $params[$this->dataLimitField] = $this->auth->id;
        }
        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
                $this->model->validateFailException()->validate($validate);
            }
            $result = $this->model->allowField(true)->save($params);
            Db::commit();
            if($params['order_num']){
                IdentityInfo::where(['id'=>$params['info_id']])->setInc('order_num_all',$params['order_num']);
            }
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($result === false) {
            $this->error(__('No rows were inserted'));
        }
        $this->success();
    }

    /**
     * 编辑
     *
     * @param $ids
     * @return string
     * @throws DbException
     * @throws \think\Exception
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
            $this->error(__('You have no permission'));
        }
        if (false === $this->request->isPost()) {
            $this->view->assign('row', $row);
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);
        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                $row->validateFailException()->validate($validate);
            }
            $result = $row->allowField(true)->save($params);
            Db::commit();
            $order_num_all = precisionRestore($params['order_num'],$row['order_num'],'减法');
            if($order_num_all){
                IdentityInfo::where(['id'=>$row['info_id']])->setInc('order_num_all',$order_num_all);
            }
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if (false === $result) {
            $this->error(__('No rows were updated'));
        }
        $this->success();
    }
}
